#include "NXmlParseHelper.h"
#include "NXmlParseMaster.h"
#include "NGame.h"
#include "NWorld.h"
#include "NFactory.h"
#include "NComponent.h"
#include "NDirector.h"

#include "NeroCore\NLogger.h"
#include "NeroCore\NAttributed.h"
#include "NeroCore\NMemoryManager.h"
#include "NeroEngine\NEntity.h"


using namespace NXML;
using namespace Utility;
using namespace Game;

NXmlParseHelper::NXmlParseHelper()
	:mXmlMaster(NULL)
{
}

NXmlParseHelper::NXmlParseHelper(NXML::NXmlParseMaster* master)
	:mXmlMaster(master)
{
	mXmlMaster->AddHelper(this);
}

NXmlParseHelper::~NXmlParseHelper()
{
	mXmlMaster = NULL;
}

bool NXmlIfHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"If"))
	{
		return true;
	}
	return false;
}

bool NXmlIfHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"If"))
	{
		return true;
	}
	return false;
}

bool NXmlLoadHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Load"))
	{
		const char* filePath = element->Attribute("file");

		NXmlParseMaster::GetInstance()->ParseXMl(filePath);

		return true;
	}
	return false;
}

bool NXmlLoadHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Load"))
	{
		return true;
	}
	return false;
}

bool NXmlSwitchHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Switch"))
	{
		return true;
	}
	return false;
}

bool NXmlSwitchHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Switch"))
	{
		return true;
	}
	return false;
}

bool NXmlForHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"For"))
	{
		return true;
	}
	return false;
}

bool NXmlForHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"For"))
	{
		return true;
	}
	return false;
}

bool NXmlTableHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Table"))
	{
		return true;
	}
	return false;
}

bool NXmlTableHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Table"))
	{
		return true;
	}
	return false;
}

bool NXmlSectorHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Sector"))
	{
		const char* sectorName = element->Attribute("name");

		GetGame()->GetWorld()->AppendSector(sectorName);

		return true;
	}
	return false;
}

bool NXmlSectorHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Sector"))
	{
		return true;
	}
	return false;
}

bool NXmlWorldHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"World"))
	{
		const char* worldName = element->Attribute("name");

		GetGame()->CreateWorld(worldName);

		return true;
	}
	return false;
}

bool NXmlWorldHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"World"))
	{
		return true;
	}
	return false;
}

bool NXmlEntityHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Entity"))
	{
		//NXML::NXmlParseMaster::NXmlSharedData* sharedData = mXmlMaster->GetSharedData();
		Engine::NEntity* entity = NULL;

		const char* className = element->Attribute("class");
		const char* instanceName = element->Attribute("instance_name");

		entity = NFactory<Engine::NEntity>::Create(className);

		if(entity != NULL)
		{
			//GetGame()->AddEntityToWorld(entity,instanceName);
			//sharedData->CurrentScope = entity;
		}
		else
		{
			std::string message = "Entity: ";
			message += className;
			message += " : ";
			message += instanceName;
			message += " ";
			message += "was not created";

			OUTLOG(message.c_str());
		}

		return true;
	}

	return false;
}

bool NXmlEntityHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Entity"))
	{
		NXML::NXmlParseMaster::NXmlSharedData* sharedData = mXmlMaster->GetSharedData();
		sharedData->CurrentScope = NULL;
		return true;
	}
	return false;
}

bool NXmlAttribueHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Attribute"))
	{
		return true;
	}
	return false;
}

bool NXmlAttribueHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Attribute"))
	{
		return true;
	}
	return false;
}

bool NXmlComponentHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Component"))
	{
		NXML::NXmlParseMaster::NXmlSharedData* sharedData = mXmlMaster->GetSharedData();
		Game::NComponent* component = NULL;
		
		TiXmlAttribute* attributes = element->FirstAttribute();

		std::string className = attributes->Value();
		component = NFactory<Game::NComponent>::Create(className);

		if(component == NULL)
		{
			return true;
		}

		attributes = attributes->Next();
		while(attributes != NULL)
		{
			component->SetData(std::pair<std::string, std::string>(attributes->Name(),attributes->Value()));

			attributes = attributes->Next();
		}

		if(component != NULL && sharedData->CurrentScope != NULL && sharedData->CurrentScope->Is("NEntity"))
		{
			//Engine::NEntity* entity = sharedData->CurrentScope->As<Engine::NEntity>();
			//entity->AddComponent(component);
		}
		else if(component != NULL)
		{
			MY_DELETE(component);
		}

		return true;
	}
	return false;
}

bool NXmlComponentHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Component"))
	{
		return true;
	}
	return false;
}

bool NXmlDirectorHelper::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Director"))
	{
		const char* initialCamera = element->Attribute("initial");

		NDirector::GetInstance()->SetInitialCamera(initialCamera);
	
		return true;
	}
	return false;
}

bool NXmlDirectorHelper::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Director"))
	{
		return true;
	}
	return false;
}

#define SUBSCRIBE(eventType, instance) Game::NEvent<eventType>::Subscribe(instance);

bool NXmlSubscribe::StartElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Subscribe"))
	{
		return true;
	}
	return false;
}

bool NXmlSubscribe::EndElementHandler(TiXmlElement* element)
{
	if(!strcmp(element->Value(),"Subscribe"))
	{
		return true;
	}
	return false;
}